package com.lkd.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.lkd.common.VMSystem;
import com.lkd.config.ConsulConfig;
import com.lkd.config.TopicConfig;
import com.lkd.contract.OrderCheck;
import com.lkd.contract.VendoutContract;
import com.lkd.contract.VendoutData;
import com.lkd.dao.OrderDao;
import com.lkd.feign.UserService;
import com.lkd.vo.*;
import com.lkd.emq.MqttProducer;
import com.lkd.entity.OrderEntity;
import com.lkd.exception.LogicException;
import com.lkd.feign.VMService;
import com.lkd.service.OrderService;
import com.lkd.utils.DistributedLock;
import com.lkd.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Autowired
    private VMService vmService;

    @Autowired
    private UserService userService;

    @Autowired
    private MqttProducer mqttProducer;

    @Override
    public OrderEntity getByOrderNo(String orderNo) {
        QueryWrapper<OrderEntity> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(OrderEntity::getOrderNo,orderNo);
        return this.getOne(qw);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderEntity createOrder(PayVO payVO) {
        /**
         *          * （1）创建订单逻辑1：通过远程调用vmService.hasCapacity 判断是否有库存 。
         *          *
         *          * （2）创建订单逻辑2：构建实体类OrderEntity，售货机相关信息通过 vmService.getVMInfo获得。
         *          *
         *          * （3）创建订单逻辑3：构建实体类OrderEntity，商品相关信息通过 vmService.getSku获得。
         *          *
         *          * （4）创建订单逻辑4：通过userService.getPartner 获得合作商，使用提成比例计算分成。
         *          *
         *          * >商品价格 * 分成比例（数据库中的金额都是乘以100）金额一定要使用BigDecimal来计算
         *          * >
         *          * >multiply乘法 divide除法
         *
         * （5）保存实体类。返回参数为订单实体类
         */

        String innerCode = payVO.getInnerCode();
        String skuId = payVO.getSkuId();
        Boolean hasCapacity = vmService.hasCapacity(innerCode, Long.valueOf(skuId));
        if(hasCapacity == null || !hasCapacity){
            throw new LogicException("售货机没有库存!");
        }

        OrderEntity orderEntity = new OrderEntity();
        //售货机编码+时间 如果服务器上的时间不一致有可能会出现重复数据
        orderEntity.setOrderNo(innerCode + System.nanoTime());
        orderEntity.setInnerCode(innerCode);
        //处理状态
        orderEntity.setStatus(VMSystem.ORDER_STATUS_CREATE);
        orderEntity.setPayStatus(VMSystem.PAY_STATUS_NOPAY);
        orderEntity.setPayType(VMSystem.PAY_TYPE_WEIXIN);
        orderEntity.setOpenId(payVO.getOpenId());

        VmVO vmInfo = vmService.getVMInfo(innerCode);
        if(vmInfo == null){
            throw new LogicException("售货机不存在!");
        }
        BeanUtils.copyProperties(vmInfo,orderEntity);
        orderEntity.setAddr(vmInfo.getNodeAddr());

        //商品信息
        SkuVO sku = vmService.getSku(skuId);
        if(sku == null){
            throw new LogicException("商品不存在!");
        }

        int realPrice = sku.getRealPrice();
        BeanUtils.copyProperties(sku,orderEntity);
        orderEntity.setPrice(realPrice);
        orderEntity.setAmount(realPrice);

        //分账数据
        PartnerVO partner = userService.getPartner(vmInfo.getOwnerId());
        if(partner != null){
            //合作商如果存在，处理分账金额
            Integer ratio = partner.getRatio(); //分账比例
            BigDecimal price = new BigDecimal(realPrice).multiply(new BigDecimal(ratio)).divide(new BigDecimal(100), 0,
                    RoundingMode.HALF_UP); //分账金额
            orderEntity.setBill(price.intValue());
        }

        save(orderEntity);

        //生成延迟消息
        OrderCheck orderCheck = new OrderCheck();
        orderCheck.setOrderNo(orderEntity.getOrderNo());
        orderCheck.setInnerCode(innerCode);
        try {
            mqttProducer.send("$delayed/10/" + TopicConfig.ORDER_CHECK_TOPIC,1, orderCheck);
        } catch (JsonProcessingException e) {
            log.error("发送订单消息时，json转换错误");
        }
        return orderEntity;
    }

}
